﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using seejee_Backendium.Core.Interfaces;
using seejee_Backendium.Core.Models;

namespace seejee_Backendium.WEB.Controllers
{
    // 添加控制器级路由：匹配/api/procedure前缀
    [Route("api/[controller]")]
    [ApiController] // 推荐添加此特性，自动处理模型验证和参数绑定
    public class ProcedureController : ControllerBase
    {
        private readonly IMemoryCache _memoryCache;
        private readonly IProcedureService _procedureService;
        private readonly IDynamicConnectionService _dynamicConnectionService;
        private readonly IBILogenAccListService _logenAccListService;
        private readonly ILogger<ProcedureController> _logger;

        public ProcedureController(
            IMemoryCache memoryCache,
            IProcedureService procedureService,
            IDynamicConnectionService dynamicConnectionService,
            IBILogenAccListService logenAccListService,
            ILogger<ProcedureController> logger)
        {
            _memoryCache = memoryCache;
            _procedureService = procedureService;
            _dynamicConnectionService = dynamicConnectionService;
            _logenAccListService = logenAccListService;
            _logger = logger;
        }

        // 方法级路由：结合控制器路由，完整路径为api/procedure/execute/{DBContent}
        [HttpPost("execute/{DBContent}")]
        public async Task<IActionResult> ExecuteProcedure(
            [FromRoute] int DBContent,
            [FromBody] ProcedureDto request)
        {
            try
            {
                // 1. 获取数据库连接信息
                BIDBContentDto dbInfo = await _logenAccListService.GetDBContentAsync(DBContent);
                if (dbInfo == null)
                {
                    return NotFound(new { success = false, message = $"DBContent {DBContent} 的数据源记录不存在" });
                }

                // 2. 构建连接字符串
                string connectionString = _dynamicConnectionService.BuildConnectionString(dbInfo);
                string cacheKey = $"db_connection_{connectionString.GetHashCode()}";

                // 3. 检查缓存中是否有有效的连接验证结果
                if (_memoryCache.TryGetValue(cacheKey, out bool isConnectedCached))
                {
                    // 如果缓存结果在30分钟内有效，直接使用
                    if (!isConnectedCached)
                    {
                        return BadRequest(new { success = false, message = "数据库连接失败（缓存结果），请与管理员确认数据源是否正确 😭" });
                    }
                    // 连接有效，跳过测试直接执行存储过程
                }
                else
                {
                    // 4. 测试连接（30秒超时）
                    using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
                    {
                        var testConnectionTask = _dynamicConnectionService.TestConnectionAsync(connectionString);
                        var timeoutTask = Task.Delay(Timeout.Infinite, cts.Token);

                        var completedTask = await Task.WhenAny(testConnectionTask, timeoutTask);

                        if (completedTask == timeoutTask)
                        {
                            // 缓存超时结果（短期缓存，避免频繁重试）
                            _memoryCache.Set(cacheKey, false, TimeSpan.FromMinutes(5));
                            return BadRequest(new { success = false, message = "数据库连接测试超时，请与管理员确认数据源是否正确 😭" });
                        }

                        bool isConnected = await testConnectionTask;

                        // 缓存连接测试结果（30分钟有效期）
                        _memoryCache.Set(cacheKey, isConnected, TimeSpan.FromMinutes(30));

                        if (!isConnected)
                        {
                            return BadRequest(new { success = false, message = "数据库连接失败，请与管理员确认数据源是否正确 😭" });
                        }
                    }
                }

                // 5. 直接使用连接字符串执行存储过程
                var result = await _procedureService.ExecuteProcedureWithConnectionAsync(request, connectionString);

                return Ok(new { success = true, data = result });
            }
            catch (ArgumentException ex)
            {
                return BadRequest(new { success = false, message = ex.Message });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "执行存储过程时发生错误，DBContent: {DBContent}", DBContent);
                return StatusCode(500, new
                {
                    success = false,
                    message = "执行存储过程时发生错误",
                    detail = ex.Message
                });
            }
        }
    }
}
